#include "RenderPch.h"

#include "ShaderToon.h"
#include "Vector4.h"

ShaderToon::ShaderToon(void) :
ShaderBase()
{
	ShaderManager * shaderManager = RenderFacade::GetInstance()->Get3DRenderer()->GetShaderManager();
	m_pEffect = shaderManager->GetD3DEffect("toon.fx");

	RenderFacade::GetInstance()->DXCreateTextureFromFile("Shader/toon.bmp", &m_pToonTexture);
	RenderFacade::GetInstance()->DXCreateTextureFromFile("Shader/ToonEdge.dds", &m_pEdgeTexture);
}

ShaderToon::~ShaderToon(void)
{
}

int ShaderToon::Begin( Material * material, DWORD fvf )
{
	m_material = material;
	m_fvf = fvf;

	UINT passCount = 0;

	m_pEffect->SetTechnique( "ToonShader" );
	m_pEffect->Begin( &passCount, 0 );

	return passCount;
}

void ShaderToon::BeginPass( int pass )
{
	m_curPass = pass;

	if( pass == 0 )	// silhouette
	{
		RenderFacade::GetInstance()->SetFVF( m_fvf );

		RenderFacade::GetInstance()->SetTexture( 0, NULL );

		DWORD silhouetteColor = 0xff000000;
		RenderFacade::GetInstance()->SetRenderState( D3DRS_TEXTUREFACTOR, silhouetteColor );
		
		RenderFacade::GetInstance()->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
		RenderFacade::GetInstance()->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TFACTOR );
		RenderFacade::GetInstance()->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
		RenderFacade::GetInstance()->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR );

		RenderFacade::GetInstance()->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
		RenderFacade::GetInstance()->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );

		Matrix world, view, proj;
		RenderFacade::GetInstance()->GetTransform( D3DTS_WORLD, &world );
		RenderFacade::GetInstance()->GetTransform( D3DTS_VIEW, &view );
		RenderFacade::GetInstance()->GetTransform( D3DTS_PROJECTION, &proj );

		Matrix matWorldViewProj = world * view * proj;
		m_pEffect->SetMatrix( "matWorldViewProj", &matWorldViewProj );

		m_pEffect->BeginPass( pass );
	}
	else if( pass == 1 ) // toon
	{
		RenderFacade::GetInstance()->SetFVF( m_fvf );

		RenderFacade::GetInstance()->SetTexture(0, m_pToonTexture);
		RenderFacade::GetInstance()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
		RenderFacade::GetInstance()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
		RenderFacade::GetInstance()->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
		RenderFacade::GetInstance()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

		Texture * texture = m_material->GetTextureData("diffuse_texture");

		if( texture )
		{
			RenderFacade::GetInstance()->SetTexture( 1, (LPDIRECT3DTEXTURE9)texture->Get() );
		}
		else
		{
			RenderFacade::GetInstance()->SetTexture( 1, NULL );
		}

		RenderFacade::GetInstance()->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
		RenderFacade::GetInstance()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		RenderFacade::GetInstance()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_NONE);
		
		RenderFacade::GetInstance()->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
		RenderFacade::GetInstance()->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
		RenderFacade::GetInstance()->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );

		RenderFacade::GetInstance()->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
		RenderFacade::GetInstance()->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

		RenderFacade::GetInstance()->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
		RenderFacade::GetInstance()->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
		RenderFacade::GetInstance()->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

		Matrix world, view, proj;
		RenderFacade::GetInstance()->GetTransform( D3DTS_WORLD, &world );
		RenderFacade::GetInstance()->GetTransform( D3DTS_VIEW, &view );
		RenderFacade::GetInstance()->GetTransform( D3DTS_PROJECTION, &proj );

		Vector4 lightDir = Vector4(0.f, 1.f, 0.f, 1.f);
		m_pEffect->SetVector( "vecLightDir", &lightDir );

		Matrix matWorldViewProj = world * view * proj;
		m_pEffect->SetMatrix( "matWorldViewProj", &matWorldViewProj );

		m_pEffect->BeginPass( pass );
	}
}

void ShaderToon::EndPass()
{
	if( m_curPass == 1 )
	{
		RenderFacade::GetInstance()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	}

	m_pEffect->EndPass();
}

void ShaderToon::End()
{
	m_pEffect->End();
}